/* 
 * created by senllang 2024/1/4 
 * mail : study@senllang.onaliyun.com 
 *
 * Copyright (c) 2023-2024 senllang

 * This is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 * http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * 
 */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void threadCleanUp(void* arg)
{
    printf("[%lu]start clean function \n",pthread_self());
	return;
}

void * thread_func(void *ignored_argument)
{
    int s;

    /* Disable cancelation for a while, so that we don't
       immediately react to a cancelation request. */

    s = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
    if (s != 0)
        perror("pthread_setcancelstate disable fail");

    pthread_cleanup_push(threadCleanUp, (char*)"first handler");

    printf("[%lu]started sleep; cancelation disabled\n",pthread_self());
    sleep(5);
    printf("[%lu]end sleep5 enable cancelation\n",pthread_self());

    s = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    if (s != 0)
        perror("pthread_setcancelstate enable fail");

    /* sleep() is a cancelation point. */
    printf("[%lu]started sleep; cancelation enabled \n",pthread_self());
    sleep(1000); /* Should get canceled while we sleep */
    printf("[%lu]end sleep; cancelation enabled \n",pthread_self());

    /* Should never get here. */
    pthread_cleanup_pop(0);
    return NULL;
}

int main(int argc, char *argv[])
{
    pthread_t thr;
    void *res;
    int s;

    /* Start a thread and then send it a cancelation request. */
    s = pthread_create(&thr, NULL, &thread_func, NULL);
    if (s != 0)
        perror( "pthread_create");

    sleep(2); /* Give thread a chance to get started */

    printf("[%lu] send cancel request to [%lu] \n",pthread_self(), thr);
    s = pthread_cancel(thr);
    if (s != 0)
        perror("pthread_cancel");

    /* Join with thread to see what its exit status was. */

    s = pthread_join(thr, &res);
    if (s != 0)
        perror( "pthread_join");

    if (res == PTHREAD_CANCELED)
        printf("[%lu] cancel thread [%lu] success \n",pthread_self(), thr);
    else
        printf("[%lu] cancel thread [%lu] failure \n",pthread_self(), thr);
    
    return 0;
}